home *** CD-ROM | disk | FTP | other *** search
/ Disc to the Future 2 / Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin / UNIX / PASCAL / PTOC / PTC_P.2 < prev    next >
Text File  |  1992-11-23  |  53KB  |  2,502 lines

  1.             if sp^.lt = lforwlab then
  2.                 sp^.lt := llabel
  3.             else
  4.                 error(emuldeflab);
  5.             end;
  6.         oldlbl := tp
  7.     end;
  8.  
  9.     (*    Parse declaration and statement-body for prog/subs.    *)
  10.     procedure pbody(tp : treeptr);
  11.  
  12.     var    tq    : treeptr;
  13.  
  14.     begin
  15.         statlvl := statlvl + 1;
  16.         if currsym.st = slabel then
  17.             begin
  18.             tp^.tsublab := plabel;
  19.             linkup(tp, tp^.tsublab)
  20.             end
  21.         else
  22.             tp^.tsublab := nil;
  23.         if currsym.st = sconst then
  24.             begin
  25.             tp^.tsubconst := pconst;
  26.             linkup(tp, tp^.tsubconst)
  27.             end
  28.         else
  29.             tp^.tsubconst := nil;
  30.         if currsym.st = stype then
  31.             begin
  32.             tp^.tsubtype := ptype;
  33.             linkup(tp, tp^.tsubtype)
  34.             end
  35.         else
  36.             tp^.tsubtype := nil;
  37.         if currsym.st = svar then
  38.             begin
  39.             tp^.tsubvar := pvar;
  40.             linkup(tp, tp^.tsubvar)
  41.             end
  42.         else
  43.             tp^.tsubvar := nil;
  44.         tp^.tsubsub := nil;
  45.         tq := nil;
  46.         while (currsym.st = sproc) or (currsym.st = sfunc) do
  47.             begin
  48.             if tq = nil then
  49.                 begin
  50.                 tq := psubs;
  51.                 tp^.tsubsub := tq
  52.                 end
  53.             else begin
  54.                 tq^.tnext := psubs;
  55.                 tq := tq^.tnext
  56.                  end
  57.             end;
  58.         linkup(tp, tp^.tsubsub);
  59.         checksymbol([sbegin, seof]);
  60.         if currsym.st = sbegin then
  61.             begin
  62.             tp^.tsubstmt := pbegin(false);
  63.             linkup(tp, tp^.tsubstmt)
  64.             end;
  65.         statlvl := statlvl - 1
  66.     end;
  67.  
  68.     (*    Parse program-declaration.                *)
  69.     function pprogram : treeptr;
  70.  
  71.     var    tp    : treeptr;
  72.  
  73.         (*    Parse a program parameter id-list.        *)
  74.         function pprmlist : treeptr;
  75.  
  76.         label    999;
  77.  
  78.         var    tp,
  79.             tq    : treeptr;
  80.             din,
  81.             dut    : idptr;
  82.  
  83.         begin
  84.             tp := nil;
  85.             din := deftab[dinput]^.tidl^.tsym^.lid;
  86.             dut := deftab[doutput]^.tidl^.tsym^.lid;
  87.             while (currsym.vid = din) or (currsym.vid = dut) do
  88.                 begin
  89.                 (* ignore input/output as parameters so that
  90.                    they will be bound to stdin/stdout unless
  91.                    declared as variables *)
  92.                 if currsym.vid = din then
  93.                     defnams[dinput]^.lused := true
  94.                 else
  95.                     defnams[doutput]^.lused := true;
  96.                 nextsymbol([scomma, srpar]);
  97.                 if currsym.st = srpar then
  98.                     goto 999;
  99.                 nextsymbol([sid])
  100.                 end;
  101.             tq := newid(currsym.vid);
  102.             tq^.tsym^.lt := lpointer;
  103.             tp := tq;
  104.             nextsymbol([scomma, srpar]);
  105.             while currsym.st = scomma do
  106.                 begin
  107.                 nextsymbol([sid]);
  108.                 if currsym.vid = din then
  109.                     defnams[dinput]^.lused := true
  110.                 else if currsym.vid = dut then
  111.                     defnams[doutput]^.lused := true
  112.                 else begin
  113.                     tq^.tnext := newid(currsym.vid);
  114.                     tq := tq^.tnext;
  115.                     tq^.tsym^.lt := lpointer;
  116.                      end;
  117.                 nextsymbol([scomma, srpar])
  118.                 end;
  119.         999:
  120.             pprmlist := tp
  121.         end;
  122.  
  123.     begin    (* pprogram *)
  124.         enterscope(nil);
  125.         tp := mknode(npgm);
  126.         nextsymbol([sid]);
  127.         tp^.tstat := statlvl;
  128.         tp^.tsubid := mknode(nid);
  129.         tp^.tsubid^.tup := tp;
  130.         tp^.tsubid^.tsym := mksym(lidentifier);
  131.         tp^.tsubid^.tsym^.lid := currsym.vid;
  132.         tp^.tsubid^.tsym^.lsymdecl := tp^.tsubid;
  133.         linkup(tp, tp^.tsubid);
  134.         nextsymbol([slpar, ssemic]);
  135.         if currsym.st = slpar then
  136.             begin
  137.             nextsymbol([sid]);
  138.             tp^.tsubpar := pprmlist;
  139.             linkup(tp, tp^.tsubpar);
  140.             nextsymbol([ssemic])
  141.             end
  142.         else
  143.             tp^.tsubpar := nil;
  144.         nextsymbol([slabel, sconst, stype, svar,
  145.                         sproc, sfunc, sbegin]);
  146.         pbody(tp);
  147.         checksymbol([sdot]);
  148.         tp^.tscope := currscope;
  149.         leavescope;
  150.         pprogram := tp
  151.     end;    (* pprogram *)
  152.  
  153.     (*    Parse a module.                *)
  154.     function pmodule : treeptr;
  155.  
  156.     var    tp    : treeptr;
  157.  
  158.     begin    (* pmodule *)
  159.         enterscope(nil);
  160.         tp := mknode(npgm);
  161.         tp^.tstat := statlvl;
  162.         tp^.tsubid := nil;
  163.         tp^.tsubpar := nil;
  164.         pbody(tp);
  165.         checksymbol([ssemic]);
  166.         tp^.tscope := currscope;
  167.         leavescope;
  168.         pmodule := tp
  169.     end;    (* pmodule *)
  170.  
  171.  
  172.     (*    Parse label-clause.                    *)
  173.     function plabel;
  174.  
  175.     var    tp,
  176.         tq    : treeptr;
  177.  
  178.     begin
  179.         tq := nil;
  180.         repeat
  181.             nextsymbol([sinteger]);
  182.             if tq = nil then
  183.                 begin
  184.                 tq := newlbl;
  185.                 tp := tq
  186.                 end
  187.             else begin
  188.                 tq^.tnext := newlbl;
  189.                 tq := tq^.tnext;
  190.                  end;
  191.             nextsymbol([scomma, ssemic])
  192.         until    currsym.st = ssemic;
  193.         nextsymbol([sconst, stype, svar, sbegin, sproc, sfunc]);
  194.         plabel := tp
  195.     end;
  196.  
  197.     (*    Parse an id-list.                    *)
  198.     function pidlist;
  199.  
  200.     var    tp,
  201.         tq    : treeptr;
  202.  
  203.     begin
  204.         tq := newid(currsym.vid);
  205.         tq^.tsym^.lt := l;
  206.         tp := tq;
  207.         nextsymbol([scomma, scolon, seq, srpar]);
  208.         while currsym.st = scomma do
  209.             begin
  210.             nextsymbol([sid]);
  211.             tq^.tnext := newid(currsym.vid);
  212.             tq := tq^.tnext;
  213.             tq^.tsym^.lt := l;
  214.             nextsymbol([scomma, scolon, seq, srpar])
  215.             end;
  216.         pidlist := tp
  217.     end;
  218.  
  219.     (*    Parse const-clause.                    *)
  220.     function pconst;
  221.  
  222.     var    tp,
  223.         tq    : treeptr;
  224.  
  225.     begin
  226.         tq := nil;
  227.         nextsymbol([sid]);
  228.         repeat
  229.             if tq = nil then
  230.                 begin
  231.                 tq := mknode(nconst);
  232.                 tq^.tattr := anone;
  233.                 tp := tq
  234.                 end
  235.             else begin
  236.                 tq^.tnext := mknode(nconst);
  237.                 tq := tq^.tnext;
  238.                 tq^.tattr := anone
  239.                  end;
  240.             tq^.tidl := pidlist(lidentifier);
  241.             checksymbol([seq]);
  242.             nextsymbol([sid, schar, sstring, sinteger, sreal,
  243.                         splus, sminus]);
  244.             tq^.tbind := pconstant(true);
  245.             nextsymbol([ssemic]);
  246.             nextsymbol([sid, stype, svar, sbegin,
  247.                             sfunc, sproc, seof])
  248.         until    currsym.st <> sid;
  249.         pconst := tp
  250.     end;
  251.  
  252.     (*    Parse a declared constant or a case-statment const.    *)
  253.     function pconstant;
  254.  
  255.     var    tp,
  256.         tq    : treeptr;
  257.         neg    : boolean;
  258.  
  259.     begin
  260.         neg := currsym.st = sminus;
  261.         if currsym.st in [splus, sminus] then
  262.             if realok then
  263.                 nextsymbol([sid, sinteger, sreal])
  264.             else
  265.                 nextsymbol([sid, sinteger]);
  266.         if currsym.st = sid then
  267.             tp := oldid(currsym.vid, lidentifier)
  268.         else
  269.             tp := mklit;
  270.         if neg then
  271.             begin
  272.             tq := mknode(numinus);
  273.             tq^.texps := tp;
  274.             tp := tq
  275.              end;
  276.         pconstant := tp
  277.     end;
  278.  
  279.     (*    Parse a record (or record-variant) declaration.        *)
  280.     (*    Cs is the expected closing symbol, dp the scope.    *)
  281.     function precord;
  282.  
  283.     label    999;
  284.  
  285.     var    tp,
  286.         tq,
  287.         tl,
  288.         tv    : treeptr;
  289.         tsym    : lexsym;
  290.  
  291.     begin
  292.         tp := mknode(nrecord);
  293.         tp^.tflist := nil;
  294.         tp^.tvlist := nil;
  295.         tp^.tuid := nil;
  296.         tp^.trscope := nil;
  297.         if cs = send then
  298.             begin
  299.             enterscope(dp);
  300.             dp := currscope
  301.             end;
  302.         nextsymbol([sid, scase] + [cs]);
  303.         tq := nil;
  304.         while currsym.st = sid do
  305.             begin
  306.             if tq = nil then
  307.                 begin
  308.                 tq := mknode(nfield);
  309.                 tq^.tattr := anone;
  310.                 tp^.tflist := tq
  311.                 end
  312.             else begin
  313.                 tq^.tnext := mknode(nfield);
  314.                 tq := tq^.tnext;
  315.                 tq^.tattr := anone
  316.                  end;
  317.             tq^.tidl := pidlist(lfield);
  318.             checksymbol([scolon]);
  319.             leavescope;
  320.             tq^.tbind := ptypedef;
  321.             enterscope(dp);
  322.             if currsym.st = ssemic then
  323.                 nextsymbol([sid, scase] + [cs])
  324.             end;
  325.         if currsym.st = scase then
  326.             begin
  327.             nextsymbol([sid]);
  328.             tsym := currsym;
  329.             nextsymbol([scolon, sof]);
  330.             if currsym.st = scolon then
  331.                 begin
  332.                 tv := newid(tsym.vid);
  333.                 if tq = nil then
  334.                     begin
  335.                     tq := mknode(nfield);
  336.                     tp^.tflist := tq
  337.                     end
  338.                 else begin
  339.                     tq^.tnext := mknode(nfield);
  340.                     tq := tq^.tnext
  341.                      end;
  342.                 tq^.tidl := tv;
  343.                 tv^.tsym^.lt := lfield;
  344.                 nextsymbol([sid]);
  345.                 leavescope;
  346.                 tq^.tbind := oldid(currsym.vid, lidentifier);
  347.                 enterscope(dp);
  348.                 nextsymbol([sof])
  349.                 end;
  350.             tq := nil;
  351.             repeat
  352.                 tv := nil;
  353.                 repeat
  354.                     nextsymbol([sid, sinteger, schar, splus,
  355.                              sminus] + [cs]);
  356.                     if currsym.st = cs then
  357.                         goto 999;
  358.                     if tv = nil then
  359.                         begin
  360.                         tv := pconstant(false);
  361.                         tl := tv
  362.                         end
  363.                     else begin
  364.                         tv^.tnext := pconstant(false);
  365.                         tv := tv^.tnext
  366.                          end;
  367.                     nextsymbol([scolon, scomma])
  368.                 until currsym.st = scolon;
  369.                 nextsymbol([slpar]);
  370.                 if tq = nil then
  371.                     begin
  372.                     tq := mknode(nvariant);
  373.                     tp^.tvlist := tq;
  374.                     end
  375.                 else begin
  376.                     tq^.tnext := mknode(nvariant);
  377.                     tq := tq^.tnext;
  378.                      end;
  379.                 tq^.tselct := tl;
  380.                 tq^.tvrnt := precord(srpar, dp)
  381.             until    currsym.st = cs
  382.             end;
  383.     999:
  384.         if cs = send then
  385.             begin
  386.             tp^.trscope := dp;
  387.             leavescope
  388.             end;
  389.         nextsymbol([ssemic, send, srpar]);
  390.         (* currsym is the symbol following record end/rpar,
  391.             (usually semicolon, sometimes enclosing end/rpar) *)
  392.         precord := tp
  393.     end;
  394.  
  395.     function ptypedef;
  396.  
  397.     var    tp,
  398.         tq    : treeptr;
  399.         st    : symtyp;
  400.         ss    : symset;
  401.  
  402.     begin
  403.         nextsymbol([sid, slpar, sarrow, sinteger, schar, splus, sminus,
  404.                 spacked, sarray, srecord, sfile, sset]);
  405.  
  406.         (* the "packed" keyword is completely ignored *)
  407.         if currsym.st = spacked then
  408.             nextsymbol([sarray, srecord, sfile, sset]);
  409.  
  410.         ss := [ssemic, send, srpar, scomma, srbrack];
  411.         case currsym.st of
  412.           splus,
  413.           sminus,
  414.           schar,
  415.           sinteger,
  416.           sid:
  417.             begin
  418.             st := currsym.st;
  419.             tp := pconstant(false);
  420.             if st = sid then
  421.                 nextsymbol([sdotdot] + ss)
  422.             else
  423.                 nextsymbol([sdotdot]);
  424.             if currsym.st = sdotdot then
  425.                 begin
  426.                 nextsymbol([sid, sinteger, schar,
  427.                                 splus, sminus]);
  428.                 tq := mknode(nsubrange);
  429.                 tq^.tlo := tp;
  430.                 tq^.thi := pconstant(false);
  431.                 tp := tq;
  432.                 nextsymbol(ss)
  433.                 end
  434.             end;
  435.           slpar:
  436.             begin
  437.             tp := mknode(nscalar);
  438.             nextsymbol([sid]);
  439.             tp^.tscalid := pidlist(lidentifier);
  440.             checksymbol([srpar]);
  441.             nextsymbol(ss)
  442.             end;
  443.           sarrow:
  444.             begin
  445.             tp := mknode(nptr);
  446.             nextsymbol([sid]);
  447.             tp^.tptrid := oldid(currsym.vid, lpointer);
  448.             tp^.tptrflag := false;
  449.             nextsymbol([ssemic, send, srpar])
  450.             end;
  451.           sarray:
  452.             begin
  453.             nextsymbol([slbrack]);
  454.             tp := mknode(narray);
  455.             tp^.taindx := ptypedef;    (* parse subrange ...    *)
  456.             tq := tp;
  457.             while currsym.st = scomma do
  458.                 begin
  459.                 (* expand:   array [ A , B ] of X
  460.                    to:   array [ A ] of array [ B ] of X   *)
  461.                 tq^.taelem := mknode(narray);
  462.                 tq := tq^.taelem;
  463.                 tq^.taindx := ptypedef    (* ... again    *)
  464.                 end;
  465.             checksymbol([srbrack]);
  466.             nextsymbol([sof]);
  467.             tq^.taelem := ptypedef
  468.             end;
  469.           srecord:
  470.             tp := precord(send, nil);
  471.           sfile,
  472.           sset:
  473.             begin
  474.             if currsym.st = sfile then
  475.                 tp := mknode(nfileof)
  476.             else begin
  477.                 tp := mknode(nsetof);
  478.                 usesets := true
  479.                  end;
  480.             nextsymbol([sof]);
  481.             tp^.tof := ptypedef
  482.             end
  483.         end;
  484.         (* at this point "currsym" holds the symbol following the type
  485.            (usually semicolon, sometimes the following end/rpar) *)
  486.         ptypedef := tp
  487.     end;
  488.  
  489.     (*    Parse type-clause.                    *)
  490.     function ptype;
  491.  
  492.     var    tp,
  493.         tq    : treeptr;
  494.  
  495.     begin
  496.         tq := nil;
  497.         nextsymbol([sid]);
  498.         repeat
  499.             if tq = nil then
  500.                 begin
  501.                 tq := mknode(ntype);
  502.                 tq^.tattr := anone;
  503.                 tp := tq
  504.                 end
  505.             else begin
  506.                 tq^.tnext := mknode(ntype);
  507.                 tq := tq^.tnext;
  508.                 tq^.tattr := anone
  509.                  end;
  510.             tq^.tidl := pidlist(lidentifier);
  511.             checksymbol([seq]);
  512.             tq^.tbind := ptypedef;
  513.             nextsymbol([sid, svar, sbegin, sfunc, sproc, seof])
  514.         until    currsym.st <> sid;
  515.         ptype := tp;
  516.     end;
  517.  
  518.     (*    Parse var-clause.                    *)
  519.     function pvar;
  520.  
  521.     var    ti,
  522.         tp,
  523.         tq    : treeptr;
  524.  
  525.     begin
  526.         tq := nil;
  527.         nextsymbol([sid]);
  528.         repeat
  529.             if tq = nil then
  530.                 begin
  531.                 tq := mknode(nvar);
  532.                 tq^.tattr := anone;
  533.                 tp := tq
  534.                 end
  535.             else begin
  536.                 tq^.tnext := mknode(nvar);
  537.                 tq := tq^.tnext;
  538.                 tq^.tattr := anone
  539.                  end;
  540.  
  541.             ti := newid(currsym.vid);
  542.             tq^.tidl := ti;
  543.             nextsymbol([scomma, scolon]);
  544.             while currsym.st = scomma do
  545.                 begin
  546.                 nextsymbol([sid]);
  547.                 ti^.tnext := newid(currsym.vid);
  548.                 ti := ti^.tnext;
  549.                 nextsymbol([scomma, scolon])
  550.                 end;
  551.  
  552.             tq^.tbind := ptypedef;
  553.             nextsymbol([sid, sbegin, sfunc, sproc, seof])
  554.         until    currsym.st <> sid;
  555.         pvar := tp
  556.     end;
  557.  
  558.     (*    Parse subroutine-declaration.                *)
  559.     function psubs;
  560.  
  561.     var    tp,            (* return value        *)
  562.         tv, tq    : treeptr;    (* temporary        *)
  563.         func    : boolean;    (* true for functions    *)
  564.         colsem    : symtyp;    (* colon/semicolon    *)
  565.  
  566.     begin
  567.         (* parsing function or procedure *)
  568.         func := currsym.st = sfunc;
  569.         if func then
  570.             colsem := scolon
  571.         else
  572.             colsem := ssemic;
  573.  
  574.         (* parse id, it may already be forward declared *)
  575.         nextsymbol([sid]);
  576.         tq := newid(currsym.vid);
  577.         if tq^.tup = nil then
  578.            begin
  579.             enterscope(nil);
  580.             (* id wasn't previously declared, params possible *)
  581.             if func then
  582.                 tp := mknode(nfunc)
  583.             else
  584.                 tp := mknode(nproc);
  585.             tp^.tstat := statlvl;
  586.             tp^.tsubid := tq;
  587.             linkup(tp, tq);
  588.             nextsymbol([slpar, colsem]);
  589.             if currsym.st = slpar then
  590.                 begin
  591.                 tp^.tsubpar := psubpar;
  592.                 linkup(tp, tp^.tsubpar);
  593.                 nextsymbol([colsem])
  594.                 end
  595.             else
  596.                 tp^.tsubpar := nil;
  597.             if func then
  598.                 begin
  599.                 (* parse function type *)
  600.                 nextsymbol([sid]);
  601.                 tp^.tfuntyp := oldid(currsym.vid, lidentifier);
  602.                 nextsymbol([ssemic])
  603.                 end
  604.             else
  605.                 tp^.tfuntyp := mknode(nempty);
  606.             linkup(tp, tp^.tfuntyp);
  607.             nextsymbol([sextern, sforward,
  608.                     slabel, sconst, stype, svar,
  609.                             sproc, sfunc, sbegin]);
  610.            end
  611.         else begin
  612.             (* id was forward declared =>
  613.                 pick up declarations from parameterlist *)
  614.             enterscope(tq^.tup^.tscope);
  615.             if func then
  616.                 tp := mknode(nfunc)
  617.             else
  618.                 tp := mknode(nproc);
  619.             tp^.tfuntyp := tq^.tup^.tfuntyp;
  620.             (* steal id and params from forward decl *)
  621.             tv := tq^.tup^.tsubpar;
  622.             tp^.tsubpar := tv;
  623.             while tv <> nil do
  624.                 begin
  625.                 tv^.tup := tp;
  626.                 tv := tv^.tnext
  627.                 end;
  628.             tp^.tsubid := tq;
  629.             tq^.tup := tp;
  630.             (* id was forward declared =>
  631.                 no params, no function type, no forward *)
  632.             nextsymbol([ssemic]);
  633.             nextsymbol([slabel, sconst, stype, svar,
  634.                             sproc, sfunc, sbegin]);
  635.              end;
  636.         if currsym.st in [sforward, sextern] then
  637.             begin
  638.             tp^.tsubid^.tsym^.lt := lforward;
  639.             nextsymbol([ssemic]);
  640.             tp^.tsublab := nil;
  641.             tp^.tsubconst := nil;
  642.             tp^.tsubtype := nil;
  643.             tp^.tsubvar := nil;
  644.             tp^.tsubsub := nil;
  645.             tp^.tsubstmt := nil
  646.             end
  647.         else
  648.             pbody(tp);
  649.         nextsymbol([sproc, sfunc, sbegin, seof]);
  650.         tp^.tscope := currscope;
  651.         leavescope;
  652.         psubs := tp
  653.     end;
  654.  
  655.     (*    Parse a conformant array index type.            *)
  656.     function pconfsub : treeptr;
  657.  
  658.     var    tp    : treeptr;
  659.  
  660.     begin
  661.         tp := mknode(nsubrange);
  662.         nextsymbol([sid]);
  663.         tp^.tlo := newid(currsym.vid);
  664.         nextsymbol([sdotdot]);
  665.         nextsymbol([sid]);
  666.         tp^.thi := newid(currsym.vid);
  667.         nextsymbol([scolon]);
  668.         pconfsub := tp
  669.     end;
  670.  
  671.     (*    Parse a conformant array-declaration.            *)
  672.     function pconform : treeptr;
  673.  
  674.     var    tp, tq    : treeptr;
  675.  
  676.     begin
  677.         nextsymbol([slbrack]);
  678.         tp := mknode(nconfarr);
  679.         tp^.tcuid := mkvariable('S');
  680.         tp^.tcindx := pconfsub;    (* parse subrange ...    *)
  681.         nextsymbol([sid]);
  682.         tp^.tindtyp := oldid(currsym.vid, lidentifier);
  683.         nextsymbol([ssemic, srbrack]);
  684.         tq := tp;
  685.         while currsym.st = ssemic do
  686.             begin
  687.             error(econfconf); (* what size does tp have *)
  688.  
  689.             (* expand:   array [ A ; B ] of X
  690.                to:   array [ A ] of array [ B ] of X   *)
  691.             tq^.tcelem := mknode(nconfarr);
  692.             tq := tq^.tcelem;
  693.             tq^.tcindx := pconfsub;    (* ... again    *)
  694.             nextsymbol([sid]);
  695.             tq^.tindtyp := oldid(currsym.vid, lidentifier);
  696.             nextsymbol([ssemic, srbrack])
  697.             end;
  698.         nextsymbol([sof]);
  699.         nextsymbol([sid, sarray]);
  700.         case currsym.st of
  701.           sid:
  702.             tq^.tcelem := oldid(currsym.vid, lidentifier);
  703.           sarray: 
  704.             begin
  705.             error(econfconf); (* what size does tp have *)
  706.  
  707.             tq^.tcelem := pconform
  708.             end;
  709.         end;(* case *)
  710.         pconform := tp
  711.     end;
  712.  
  713.     (*    Parse subroutine parameter list.            *)
  714.     function psubpar;
  715.  
  716.     var    tp,
  717.         tq    : treeptr;
  718.         nt    : treetyp;
  719.  
  720.     begin
  721.         tq := nil;
  722.         repeat
  723.             nextsymbol([sid, svar, sfunc, sproc]);
  724.             case currsym.st of
  725.               sid:
  726.                 nt := nvalpar;
  727.               svar:
  728.                 nt := nvarpar;
  729.               sfunc:
  730.                 nt := nparfunc;
  731.               sproc:
  732.                 nt := nparproc;
  733.             end;
  734.             if nt <> nvalpar then
  735.                 nextsymbol([sid]);
  736.             if tq = nil then
  737.                 begin
  738.                 tq := mknode(nt);
  739.                 tp := tq
  740.                 end
  741.             else begin
  742.                 tq^.tnext := mknode(nt);
  743.                 tq := tq^.tnext
  744.                  end;
  745.             case nt of
  746.               nvarpar,
  747.               nvalpar:
  748.                 begin
  749.                 tq^.tidl := pidlist(lidentifier);
  750.                 tq^.tattr := anone;
  751.                 checksymbol([scolon]);
  752.                 if nt = nvalpar then
  753.                     nextsymbol([sid])
  754.                 else
  755.                     nextsymbol([sid, sarray]);
  756.                 case currsym.st of
  757.                   sid:
  758.                     tq^.tbind :=
  759.                         oldid(currsym.vid, lidentifier);
  760.                   sarray:
  761.                     tq^.tbind := pconform
  762.                 end;(* case *)
  763.                 nextsymbol([srpar, ssemic])
  764.                 end;
  765.               nparproc:
  766.                 begin
  767.                 tq^.tparid := newid(currsym.vid);
  768.                 nextsymbol([ssemic, slpar, srpar]);
  769.                 if currsym.st = slpar then
  770.                     begin
  771.                     enterscope(nil);
  772.                     tq^.tparparm := psubpar;
  773.                     nextsymbol([ssemic, srpar]);
  774.                     leavescope
  775.                     end
  776.                 else
  777.                     tq^.tparparm := nil;
  778.                 tq^.tpartyp := nil
  779.                 end;
  780.               nparfunc:
  781.                 begin
  782.                 tq^.tparid := newid(currsym.vid);
  783.                 nextsymbol([scolon, slpar]);
  784.                 if currsym.st = slpar then
  785.                     begin
  786.                     enterscope(nil);
  787.                     tq^.tparparm := psubpar;
  788.                     nextsymbol([scolon]);
  789.                     leavescope
  790.                     end
  791.                 else
  792.                     tq^.tparparm := nil;
  793.                 nextsymbol([sid]);
  794.                 tq^.tpartyp := oldid(currsym.vid, lidentifier);
  795.                 nextsymbol([srpar, ssemic])
  796.                 end
  797.             end (* case *)
  798.         until    currsym.st = srpar;
  799.         psubpar := tp
  800.     end;
  801.  
  802.     (*    Parse a (possibly labeled) statement.            *)
  803.     function plabstmt;
  804.  
  805.     var    tp    : treeptr;
  806.  
  807.     begin
  808.         nextsymbol([sid, sinteger, sif, swhile, srepeat, sfor, scase,
  809.                   swith, sbegin, sgoto,
  810.                     selse, ssemic, send, suntil]);
  811.         if currsym.st = sinteger then
  812.             begin
  813.             tp := mknode(nlabstmt);
  814.             tp^.tlabno := oldlbl(true);
  815.             nextsymbol([scolon]);
  816.             nextsymbol([sid, sif, swhile, srepeat, sfor, scase,
  817.                   swith, sbegin, sgoto,
  818.                     selse, ssemic, send, suntil]);
  819.             tp^.tstmt := pstmt
  820.             end
  821.         else
  822.             tp := pstmt;
  823.         plabstmt := tp
  824.     end;
  825.  
  826.     (*    Parse an unlabeled statement.                *)
  827.     function pstmt;
  828.  
  829.     var    tp    : treeptr;
  830.  
  831.     begin
  832.         case currsym.st of
  833.           sid:
  834.             tp := psimple;
  835.           sif:
  836.             tp := pif;
  837.           swhile:
  838.             tp := pwhile;
  839.           srepeat:
  840.             tp := prepeat;
  841.           sfor:
  842.             tp := pfor;
  843.           scase:
  844.             tp := pcase;
  845.           swith:
  846.             tp := pwith;
  847.           sbegin:
  848.             tp := pbegin(true);
  849.           sgoto:
  850.             tp := pgoto;
  851.           send,
  852.           selse,
  853.           suntil,
  854.           ssemic:
  855.             tp := mknode(nempty);
  856.         end;
  857.         pstmt := tp
  858.     end;
  859.  
  860.     (*    Parse an assignment or a procedure call.        *)
  861.     function psimple;
  862.  
  863.     var    tq,
  864.         tp    : treeptr;
  865.  
  866.     begin
  867.         tp := pvariable(oldid(currsym.vid, lidentifier));
  868.         if currsym.st = sassign then
  869.             begin
  870.             tq := mknode(nassign);
  871.             tq^.tlhs := tp;
  872.             tq^.trhs := pexpr(nil);
  873.             tp := tq
  874.             end;
  875.         psimple := tp
  876.     end;
  877.  
  878.     (*    Parse a varable-reference (or a subroutine-call).    *)
  879.     function pvariable;
  880.  
  881.     var    tp,
  882.         tq    : treeptr;
  883.  
  884.     begin
  885.         nextsymbol([slpar, slbrack, sdot, sarrow,
  886.             sassign, ssemic, scomma, scolon, sdotdot,
  887.             splus, sminus, smul, sdiv, smod, squot,
  888.             sand, sor, sinn, srpar, srbrack,
  889.             sle, slt, seq, sge, sgt, sne,
  890.             send, suntil, sthen, selse, sdo, sdownto, sto, sof]);
  891.         if currsym.st in [slpar, slbrack, sdot, sarrow] then
  892.             begin
  893.             case currsym.st of
  894.               slpar:
  895.                 begin
  896.                 tp := mknode(ncall);
  897.                 tp^.tcall := varptr;
  898.                 tq := nil;
  899.                 repeat
  900.                     if tq = nil then
  901.                         begin
  902.                         tq := pexpr(nil);
  903.                         tp^.taparm  := tq
  904.                         end
  905.                     else begin
  906.                         tq^.tnext := pexpr(nil);
  907.                         tq := tq^.tnext
  908.                          end;
  909.                 until    currsym.st = srpar
  910.                 end;
  911.               slbrack:
  912.                 begin
  913.                 tq := varptr;
  914.                 repeat
  915.                     tp := mknode(nindex);
  916.                     tp^.tvariable := tq;
  917.                     tp^.toffset := pexpr(nil);
  918.                     tq := tp
  919.                 until    currsym.st = srbrack
  920.                 end;
  921.               sdot:
  922.                 begin
  923.                 tp := mknode(nselect);
  924.                 tp^.trecord := varptr;
  925.                 nextsymbol([sid]);
  926.                 tq := typeof(varptr);
  927.                 enterscope(tq^.trscope);
  928.                 tp^.tfield := oldid(currsym.vid, lfield);
  929.                 leavescope
  930.                 end;
  931.               sarrow:
  932.                 begin
  933.                 tp := mknode(nderef);
  934.                 tp^.texps := varptr
  935.                 end
  936.             end;(* case *)
  937.             tp := pvariable(tp)
  938.             end
  939.         else begin
  940.             tp := varptr;
  941.             if tp^.tt = nid then
  942.                 begin
  943.                 tq := idup(tp);
  944.                 if tq <> nil then
  945.                     if tq^.tt in [nfunc, nproc,
  946.                             nparproc, nparfunc] then
  947.                         begin
  948.                         (* subroutine-call without
  949.                            parameters *)
  950.                         tp := mknode(ncall);
  951.                         tp^.tcall := varptr;
  952.                         tp^.taparm := nil
  953.                         end
  954.                 end
  955.              end;
  956.         pvariable := tp
  957.     end;
  958.  
  959.     (*    Parse an expression.                    *)
  960.     function pexpr;
  961.  
  962.     var    tp,
  963.         tq    : treeptr;
  964.         nt    : treetyp;
  965.         next    : boolean;
  966.  
  967.         function padjust(tu, tr : treeptr) : treeptr;
  968.         begin
  969.             if pprio[tu^.tt] >= pprio[tr^.tt] then
  970.                 begin
  971.                 if tr^.tt in [nnot, numinus, nuplus,
  972.                             nset, nderef] then
  973.                     tr^.texps := padjust(tu, tr^.texps)
  974.                 else
  975.                     tr^.texpl := padjust(tu, tr^.texpl);
  976.                 padjust := tr
  977.                 end
  978.             else begin
  979.                 if tu^.tt in [nnot, numinus, nuplus,
  980.                             nset, nderef] then
  981.                     tu^.texps := tr
  982.                 else
  983.                     tu^.texpr := tr;
  984.                 padjust := tu
  985.                  end
  986.         end;
  987.  
  988.     begin
  989.         nextsymbol([sid, schar, sinteger, sreal, sstring, snil,
  990.                 splus, sminus, snot, slpar, slbrack, srbrack]);
  991.         next := true;
  992.         case currsym.st of
  993.           splus:
  994.             begin
  995.             tp := mknode(nuplus);
  996.             tp^.texps := nil;
  997.             tp := pexpr(tp);
  998.             next := false
  999.             end;
  1000.           sminus:
  1001.             begin
  1002.             tp := mknode(numinus);
  1003.             tp^.texps := nil;
  1004.             tp := pexpr(tp);
  1005.             next := false
  1006.             end;
  1007.           snot:
  1008.             begin
  1009.             tp := mknode(nnot);
  1010.             tp^.texps := nil;
  1011.             tp := pexpr(tp);
  1012.             next := false
  1013.             end;
  1014.           schar,
  1015.           sinteger,
  1016.           sreal,
  1017.           sstring:
  1018.             tp := mklit;
  1019.           snil:
  1020.             begin
  1021.             usenilp := true;
  1022.             tp := mknode(nnil);
  1023.             end;
  1024.           sid:
  1025.             begin
  1026.             tp := pvariable(oldid(currsym.vid, lidentifier));
  1027.             next := false
  1028.             end;
  1029.           slpar:
  1030.             begin
  1031.             tp := mknode(nuplus);
  1032.             tp^.texps := pexpr(nil)
  1033.             end;
  1034.           slbrack:
  1035.             begin
  1036.             usesets := true;
  1037.             tp := mknode(nset);
  1038.             tp^.texps := nil;
  1039.             tq := nil;
  1040.             repeat
  1041.                 if tq = nil then
  1042.                     begin
  1043.                     tq := pexpr(nil);
  1044.                     tp^.texps := tq
  1045.                     end
  1046.                 else begin
  1047.                     tq^.tnext := pexpr(nil);
  1048.                     tq := tq^.tnext
  1049.                      end
  1050.             until    currsym.st = srbrack;
  1051.             end;
  1052.           srbrack:
  1053.             begin
  1054.             tp := mknode(nempty);
  1055.             next := false
  1056.             end
  1057.         end;
  1058.         if next then
  1059.             nextsymbol([
  1060.                 scolon, ssemic, scomma, sdotdot, srpar, srbrack,
  1061.                 sle, slt, seq, sge, sgt, sne,
  1062.                 splus, sminus, smul, sdiv, smod, squot,
  1063.                 sand, sor, sinn,
  1064.                 send, suntil, sthen, selse, sdo, sdownto, sto,
  1065.                 sof, slpar, slbrack]);
  1066.         case currsym.st of
  1067.           sdotdot:
  1068.             nt := nrange;
  1069.           splus:
  1070.             nt := nplus;
  1071.           sminus:
  1072.             nt := nminus;
  1073.           smul:
  1074.             nt := nmul;
  1075.           sdiv:
  1076.             nt := ndiv;
  1077.           smod:
  1078.             nt := nmod;
  1079.           squot:
  1080.             begin
  1081.             defnams[dreal]^.lused := true;
  1082.             nt := nquot;
  1083.             end;
  1084.           sand:
  1085.             nt := nand;
  1086.           sor:
  1087.             nt := nor;
  1088.           sinn:
  1089.             begin
  1090.             nt := nin;
  1091.             usesets := true
  1092.             end;
  1093.           sle:
  1094.             nt := nle;
  1095.           slt:
  1096.             nt := nlt;
  1097.           seq:
  1098.             nt := neq;
  1099.           sge:
  1100.             nt := nge;
  1101.           sgt:
  1102.             nt := ngt;
  1103.           sne:
  1104.             nt := nne;
  1105.           scolon:
  1106.             nt := nformat;
  1107.           sid, schar, sinteger, sreal, sstring, snil,
  1108.           ssemic, scomma, slpar, slbrack, srpar, srbrack,
  1109.           send, suntil, sthen, selse, sdo, sdownto, sto, sof:
  1110.             nt := nnil
  1111.         end;(* case *)
  1112.         if nt in [nin .. nor, nand, nnot] then
  1113.             defnams[dboolean]^.lused := true;
  1114.         if nt <> nnil then
  1115.             begin
  1116.             (* binary operator *)
  1117.             tq := mknode(nt);
  1118.             tq^.texpl := tp;
  1119.             tq^.texpr := nil;
  1120.             tp := pexpr(tq)
  1121.             end;
  1122.  
  1123.         (* this statement yilds proper operator precedence *)
  1124.         if tnp <> nil then
  1125.             tp := padjust(tnp, tp);
  1126.         pexpr := tp
  1127.     end;
  1128.  
  1129.     (*    Parse a case-statement.                    *)
  1130.     function pcase;
  1131.  
  1132.     label    999;
  1133.  
  1134.     var    tp,
  1135.         tq,
  1136.         tv    : treeptr;
  1137.  
  1138.     begin
  1139.         tp := mknode(ncase);
  1140.         tp^.tcasxp := pexpr(nil);
  1141.         checksymbol([sof]);
  1142.         tq := nil;
  1143.         repeat
  1144.             if tq = nil then
  1145.                 begin
  1146.                 tq := mknode(nchoise);
  1147.                 tp^.tcaslst := tq
  1148.                 end
  1149.             else begin
  1150.                 tq^.tnext := mknode(nchoise);
  1151.                 tq := tq^.tnext
  1152.                  end;
  1153.             tv := nil;
  1154.             repeat
  1155.                 nextsymbol([sid, sinteger, schar,
  1156.                         splus, sminus, send, sother]);
  1157.                 if currsym.st in [send, sother] then
  1158.                     goto 999;
  1159.                 if tv = nil then
  1160.                     begin
  1161.                     tv := pconstant(false);
  1162.                     tq^.tchocon := tv
  1163.                     end
  1164.                 else begin
  1165.                     tv^.tnext := pconstant(false);
  1166.                     tv := tv^.tnext
  1167.                      end;
  1168.                 nextsymbol([scomma, scolon])
  1169.             until    currsym.st = scolon;
  1170.             tq^.tchostmt := plabstmt
  1171.         until    currsym.st = send;
  1172.     999:
  1173.         if currsym.st = sother then
  1174.             begin
  1175.             nextsymbol([scolon, sid, sif, swhile, srepeat, sfor,
  1176.                     scase, swith, sbegin, sgoto,
  1177.                     selse, ssemic, send, suntil]);
  1178.             if currsym.st = scolon then
  1179.                 nextsymbol([sid, sif, swhile, srepeat, sfor,
  1180.                     scase, swith, sbegin, sgoto,
  1181.                     selse, ssemic, send, suntil]);
  1182.             tp^.tcasother := pstmt
  1183.             end
  1184.         else begin
  1185.             tp^.tcasother := nil;
  1186.             usecase := true
  1187.              end;
  1188.         nextsymbol([ssemic, send, selse, suntil]);
  1189.         pcase := tp
  1190.     end;
  1191.  
  1192.     (*    Parse an if-statement.                    *)
  1193.     function pif;
  1194.  
  1195.     var    tp    : treeptr;
  1196.  
  1197.     begin
  1198.         tp := mknode(nif);
  1199.         tp^.tifxp := pexpr(nil);
  1200.         checksymbol([sthen]);
  1201.         tp^.tthen := plabstmt;
  1202.         if currsym.st = selse then
  1203.             tp^.telse := plabstmt
  1204.         else
  1205.             tp^.telse := nil;
  1206.         pif := tp;
  1207.     end;
  1208.  
  1209.     (*    Parse a while-statement.                *)
  1210.     function pwhile;
  1211.  
  1212.     var    tp    : treeptr;
  1213.  
  1214.     begin
  1215.         tp := mknode(nwhile);
  1216.         tp^.twhixp := pexpr(nil);
  1217.         checksymbol([sdo]);
  1218.         tp^.twhistmt := plabstmt;
  1219.         pwhile := tp;
  1220.     end;
  1221.  
  1222.     (*    Parse a repeat-statement.                *)
  1223.     function prepeat;
  1224.  
  1225.     var    tp,
  1226.         tq    : treeptr;
  1227.  
  1228.     begin
  1229.         tp := mknode(nrepeat);
  1230.         tq := nil;
  1231.         repeat
  1232.             if tq = nil then
  1233.                 begin
  1234.                 tq := plabstmt;
  1235.                 tp^.treptstmt := tq
  1236.                 end
  1237.             else begin
  1238.                 tq^.tnext := plabstmt;
  1239.                 tq := tq^.tnext
  1240.                  end;
  1241.             checksymbol([ssemic, suntil])
  1242.         until    currsym.st = suntil;
  1243.         tp^.treptxp := pexpr(nil);
  1244.         prepeat := tp
  1245.     end;
  1246.  
  1247.     (*    Parse a for-statement.                    *)
  1248.     function pfor;
  1249.  
  1250.     var    tp    : treeptr;
  1251.  
  1252.     begin
  1253.         tp := mknode(nfor);
  1254.         nextsymbol([sid]);
  1255.         tp^.tforid := oldid(currsym.vid, lidentifier);
  1256.         nextsymbol([sassign]);
  1257.         tp^.tfrom := pexpr(nil);
  1258.         checksymbol([sdownto, sto]);
  1259.         tp^.tincr := currsym.st = sto;
  1260.         tp^.tto := pexpr(nil);
  1261.         checksymbol([sdo]);
  1262.         tp^.tforstmt := plabstmt;
  1263.         pfor := tp
  1264.     end;
  1265.  
  1266.     (*    Parse a with-statement.                    *)
  1267.     function pwith;
  1268.  
  1269.     var    tp,
  1270.         tq    : treeptr;
  1271.  
  1272.     begin
  1273.         tp := mknode(nwith);
  1274.         tq := nil;
  1275.         repeat
  1276.             if tq = nil then
  1277.                 begin
  1278.                 tq := mknode(nwithvar);
  1279.                 tp^.twithvar := tq
  1280.                 end
  1281.             else begin
  1282.                 tq^.tnext := mknode(nwithvar);
  1283.                 tq := tq^.tnext
  1284.                  end;
  1285.             enterscope(nil);
  1286.             tq^.tenv := currscope;
  1287.             tq^.texpw := pexpr(nil);
  1288.             scopeup(tq^.texpw);
  1289.             checksymbol([scomma, sdo])
  1290.         until    currsym.st = sdo;
  1291.         tp^.twithstmt := plabstmt;
  1292.         tq := tp^.twithvar;
  1293.         while tq <> nil do
  1294.             begin
  1295.             leavescope;
  1296.             tq := tq^.tnext
  1297.             end;
  1298.         pwith := tp
  1299.     end;
  1300.  
  1301.     (*    Parse a goto-statement.                    *)
  1302.     function pgoto;
  1303.  
  1304.     var    tp    : treeptr;
  1305.  
  1306.     begin
  1307.         nextsymbol([sinteger]);
  1308.         tp := mknode(ngoto);
  1309.         tp^.tlabel := oldlbl(false);
  1310.         nextsymbol([ssemic, send, suntil, selse]);
  1311.         pgoto := tp
  1312.     end;
  1313.  
  1314.     (*    Parse a begin-statement.                *)
  1315.     function pbegin;
  1316.  
  1317.     var    tp,
  1318.         tq    : treeptr;
  1319.  
  1320.     begin
  1321.         tq := nil;
  1322.         repeat
  1323.             if tq = nil then
  1324.                 begin
  1325.                 tq := plabstmt;
  1326.                 tp := tq
  1327.                 end
  1328.             else begin
  1329.                 tq^.tnext := plabstmt;
  1330.                 tq := tq^.tnext
  1331.                  end
  1332.         until    currsym.st = send;
  1333.         if retain then
  1334.             begin
  1335.             tq := mknode(nbegin);
  1336.             tq^.tbegin := tp;
  1337.             tp := tq
  1338.             end;
  1339.         nextsymbol([send, selse, suntil, sdot, ssemic]);
  1340.         pbegin := tp
  1341.     end;
  1342.  
  1343. begin    (* parse *)
  1344.     nextsymbol([spgm, sconst, stype, svar, sproc, sfunc]);
  1345.     if currsym.st = spgm then
  1346.         top := pprogram
  1347.     else
  1348.         top := pmodule;
  1349.     nextsymbol([seof]);
  1350. end;    (* parse *)
  1351.  
  1352. (*    Compute value for a node (which must be some kind of constant).    *)
  1353. function cvalof(tp : treeptr) : integer;
  1354.  
  1355. var    v    : integer;
  1356.     tq    : treeptr;
  1357.  
  1358. begin
  1359.     case tp^.tt of
  1360.       nuplus:
  1361.         cvalof := cvalof(tp^.texps);
  1362.       numinus:
  1363.         cvalof := - cvalof(tp^.texps);
  1364.       nnot:
  1365.         cvalof := 1 - cvalof(tp^.texps);
  1366.       nid:
  1367.         begin
  1368.         tq := idup(tp);
  1369.         if tq = nil then
  1370.             fatal(etree);
  1371.         tp := tp^.tsym^.lsymdecl;
  1372.         case tq^.tt of
  1373.           nscalar:
  1374.             begin
  1375.             v := 0;
  1376.             tq := tq^.tscalid;
  1377.             while tq <> nil do
  1378.                 if tq = tp then
  1379.                     tq := nil
  1380.                 else begin
  1381.                     v := v + 1;
  1382.                     tq := tq^.tnext
  1383.                      end;
  1384.             cvalof := v
  1385.             end;
  1386.           nconst:
  1387.             cvalof := cvalof(tq^.tbind);
  1388.         end;(* case *)
  1389.         end;
  1390.       ninteger:
  1391.         cvalof := tp^.tsym^.linum;
  1392.       nchar:
  1393.         cvalof := ord(tp^.tsym^.lchar);
  1394.     end (* case *)
  1395. end;    (* cvalof *)
  1396.  
  1397. (*    Compute lower value of subrange or scalar type.            *)
  1398. function clower(tp : treeptr) : integer;
  1399.  
  1400. var    tq    : treeptr;
  1401.  
  1402. begin
  1403.     tq := typeof(tp);
  1404.     if tq^.tt = nscalar then
  1405.         clower := scalbase
  1406.     else if tq^.tt = nsubrange then
  1407.         if tq^.tup^.tt = nconfarr then
  1408.             clower := 0
  1409.         else
  1410.             clower := cvalof(tq^.tlo)
  1411.     else if tq = typnods[tchar] then
  1412.         clower := 0
  1413.     else if tq = typnods[tinteger] then
  1414.         clower := -maxint
  1415.     else
  1416.         fatal(etree)
  1417. end;    (* clower *)
  1418.  
  1419. (*    Compute upper value of subrange or scalar type.            *)
  1420. function cupper(tp : treeptr) : integer;
  1421.  
  1422. var    tq    : treeptr;
  1423.     i    : integer;
  1424.  
  1425. begin
  1426.     tq := typeof(tp);
  1427.     if tq^.tt = nscalar then
  1428.         begin
  1429.         tq := tq^.tscalid;
  1430.         i := scalbase;
  1431.         while tq^.tnext <> nil do
  1432.             begin
  1433.             i := i + 1;
  1434.             tq := tq^.tnext
  1435.             end;
  1436.         cupper := i
  1437.         end
  1438.     else if tq^.tt = nsubrange then
  1439.         if tq^.tup^.tt = nconfarr then
  1440.             fatal(euprconf)
  1441.         else
  1442.             cupper := cvalof(tq^.thi)
  1443.     else if tq = typnods[tchar] then
  1444.         cupper := maxchar
  1445.     else if tq = typnods[tinteger] then
  1446.         cupper := maxint
  1447.     else
  1448.         fatal(etree)
  1449. end;    (* cupper *)
  1450.  
  1451. (*    Compute the number of elements in a subrange.            *)
  1452. function crange(tp : treeptr) : integer;
  1453.  
  1454. begin
  1455.     crange := cupper(tp) - clower(tp) + 1
  1456. end;
  1457.  
  1458. (*    Return number of words uset to store a set.            *)
  1459. function csetwords(i : integer) : integer;
  1460.  
  1461. begin
  1462.     i := (i+(setbits)) div (setbits+1);
  1463.     if i > maxsetrange then
  1464.         error(esetsize);
  1465.     csetwords := i
  1466. end;
  1467.  
  1468. (*    Return number of words uset to store a set.            *)
  1469. function csetsize(tp : treeptr) : integer;
  1470.  
  1471. var    tq    : treeptr;
  1472.     i    : integer;
  1473.  
  1474. begin
  1475.     tq := typeof(tp^.tof);
  1476.     i := clower(tq);
  1477.     (* bits in sets are always numbered from 0, so we (arbitrarily)
  1478.        decide that the base must be in the first 6 words to avoid
  1479.        unnecessary waste of space *)
  1480.     if (i < 0) or (i >= 6 * (setbits+1))  then
  1481.         error(esetbase);
  1482.     csetsize := csetwords(crange(tq)) + 1
  1483. end;
  1484.  
  1485. (*    Determine if tp is declared in the procedure it is used in.    *)
  1486. function islocal(tp : treeptr) : boolean;
  1487.  
  1488. var    tq    : treeptr;
  1489.  
  1490. begin
  1491.     tq := tp^.tsym^.lsymdecl;
  1492.     while not (tq^.tt in [nproc, nfunc, npgm]) do
  1493.         tq := tq^.tup;
  1494.     while not (tp^.tt in [nproc, nfunc, npgm]) do
  1495.         tp := tp^.tup;
  1496.     islocal := tp = tq
  1497. end;
  1498.  
  1499. (*    Perform necessary transformations on tree and identifiers    *)
  1500. (*    before generating code.                        *)
  1501. procedure transform;
  1502.  
  1503.  
  1504.     (*    Rename function when used as a variable.        *)
  1505.     procedure renamf(tp : treeptr);
  1506.  
  1507.     var    ip, iq    : symptr;
  1508.         tq, tv    : treeptr;
  1509.  
  1510.         (*    This procedure recursively descends the tree    *)
  1511.         (*    and replaces function-assignments with variable    *)
  1512.         (*    assignments.                    *)
  1513.         procedure crtnvar(tp : treeptr);
  1514.  
  1515.         begin
  1516.             while tp <> nil do
  1517.                 begin
  1518.                 case tp^.tt of
  1519.                   npgm:
  1520.                     crtnvar(tp^.tsubsub);
  1521.                   nfunc,
  1522.                   nproc:
  1523.                     begin
  1524.                     crtnvar(tp^.tsubsub);
  1525.                     crtnvar(tp^.tsubstmt)
  1526.                     end;
  1527.                   nbegin:
  1528.                     crtnvar(tp^.tbegin);
  1529.                   nif:
  1530.                     begin
  1531.                     crtnvar(tp^.tthen);
  1532.                     crtnvar(tp^.telse)
  1533.                     end;
  1534.                   nwhile:
  1535.                     crtnvar(tp^.twhistmt);
  1536.                   nrepeat:
  1537.                     crtnvar(tp^.treptstmt);
  1538.                   nfor:
  1539.                     crtnvar(tp^.tforstmt);
  1540.                   ncase:
  1541.                     begin
  1542.                     crtnvar(tp^.tcaslst);
  1543.                     crtnvar(tp^.tcasother)
  1544.                     end;
  1545.                   nchoise:
  1546.                     crtnvar(tp^.tchostmt);
  1547.                   nwith:
  1548.                     crtnvar(tp^.twithstmt);
  1549.                   nlabstmt:
  1550.                     crtnvar(tp^.tstmt);
  1551.                   nassign:
  1552.                     begin
  1553.                     (* revoke calls in assignment lhs, (mis-
  1554.                        parsed due to ambiguous syntax) *)
  1555.                     if tp^.tlhs^.tt = ncall then
  1556.                         begin
  1557.                         tp^.tlhs := tp^.tlhs^.tcall;
  1558.                         tp^.tlhs^.tup := tp
  1559.                         end;
  1560.                     (* function name -> variable name *)
  1561.                     tv := tp^.tlhs;
  1562.                     if tv^.tt = nid then
  1563.                         if tv^.tsym = ip then
  1564.                             tv^.tsym := iq
  1565.                     end;
  1566.                   nbreak,
  1567.                   npush,
  1568.                   npop,
  1569.                   ngoto,
  1570.                   nempty,
  1571.                   ncall:
  1572.                     (* no op *)
  1573.                 end;(* case *)
  1574.                 tp := tp^.tnext
  1575.                 end
  1576.         end;
  1577.  
  1578.     begin    (* renamf *)
  1579.         while tp <> nil do
  1580.             begin
  1581.             case tp^.tt of
  1582.               npgm,
  1583.               nproc:
  1584.                 renamf(tp^.tsubsub);
  1585.               nfunc:
  1586.                 begin
  1587.                 (* create a variable to hold return value *)
  1588.                 tq := mknode(nvar);
  1589.                 tq^.tattr := aregister;
  1590.                 tq^.tup := tp;
  1591.                 tq^.tidl := newid(mkvariable('R'));
  1592.                 tq^.tidl^.tup := tq;
  1593.                 tq^.tbind := tp^.tfuntyp;
  1594.                 (* put it FIRST among variables, see esubr() *)
  1595.                 tq^.tnext := tp^.tsubvar;
  1596.                 tp^.tsubvar := tq;
  1597.  
  1598.                 iq := tq^.tidl^.tsym;
  1599.                 ip := tp^.tsubid^.tsym;
  1600.                 crtnvar(tp^.tsubsub);
  1601.                 crtnvar(tp^.tsubstmt);
  1602.                 (* process inner functions *)
  1603.                 renamf(tp^.tsubsub)
  1604.                 end;
  1605.             end;(* case *)
  1606.             tp := tp^.tnext
  1607.             end
  1608.     end;    (* renamf *)
  1609.  
  1610.     (*    This procedure rearranges the tree such that multiple    *)
  1611.     (*    vardeclarations don't have (structured) types attached    *)
  1612.     (*    to them. If such a declararation is found, a new name    *)
  1613.     (*    is created and the type is moved to the type section.    *)
  1614.     procedure extract(tp : treeptr);
  1615.  
  1616.     var    vp    : treeptr;
  1617.  
  1618.         (*    Create a declaration for tp, enter in pp type-    *)
  1619.         (*    list and return an identifier referencing it.    *)
  1620.         function xtrit(tp, pp : treeptr; last : boolean) : treeptr;
  1621.  
  1622.         var    np, rp    : treeptr;
  1623.             ip    : idptr;
  1624.  
  1625.         begin
  1626.             (* create new declaration *)
  1627.             np := mknode(ntype);
  1628.             ip := mkvariable('T');
  1629.             np^.tidl := newid(ip);
  1630.             np^.tidl^.tup := np;
  1631.  
  1632.             (* create substitute id *)
  1633.             rp := oldid(ip, lidentifier);
  1634.             rp^.tup := tp^.tup;
  1635.             rp^.tnext := tp^.tnext;
  1636.  
  1637.             (* steal type description *)
  1638.             np^.tbind := tp;
  1639.             tp^.tup := np;
  1640.             tp^.tnext := nil;
  1641.  
  1642.             (* add new declaration to tree *)
  1643.             np^.tup := pp;
  1644.             if last and (pp^.tsubtype <> nil) then
  1645.                 begin
  1646.                 pp := pp^.tsubtype;
  1647.                 while pp^.tnext <> nil do
  1648.                     pp := pp^.tnext;
  1649.                 pp^.tnext := np
  1650.                 end
  1651.             else begin
  1652.                 np^.tnext := pp^.tsubtype;
  1653.                 pp^.tsubtype := np;
  1654.                 end;
  1655.  
  1656.             xtrit := rp;
  1657.         end;
  1658.  
  1659.         (*    Extract anonymous enumeration types.        *)
  1660.         function xtrenum(tp, pp : treeptr) : treeptr;
  1661.  
  1662.             (*    Name record-types referenced by ptrs.    *)
  1663.             procedure nametype(tp : treeptr);
  1664.  
  1665.             begin
  1666.                 tp := typeof(tp);
  1667.                 if tp^.tt = nrecord then
  1668.                     if tp^.tuid = nil then
  1669.                         tp^.tuid := mkvariable('S');
  1670.             end;
  1671.  
  1672.         begin
  1673.             if tp <> nil then
  1674.                 begin
  1675.                 case tp^.tt of
  1676.                   nfield,
  1677.                   ntype,
  1678.                   nvar:
  1679.                     tp^.tbind :=
  1680.                         xtrenum(tp^.tbind, pp);
  1681.  
  1682.                   nscalar:
  1683.                     if tp^.tup^.tt <> ntype then
  1684.                         tp := xtrit(tp, pp, false);
  1685.  
  1686.                   narray:
  1687.                     begin
  1688.                     tp^.taindx := xtrenum(tp^.taindx, pp);
  1689.                     tp^.taelem := xtrenum(tp^.taelem, pp);
  1690.                     end;
  1691.                   nrecord:
  1692.                     begin
  1693.                     tp^.tflist := xtrenum(tp^.tflist, pp);
  1694.                     tp^.tvlist := xtrenum(tp^.tvlist, pp);
  1695.                     end;
  1696.                   nvariant:
  1697.                     tp^.tvrnt := xtrenum(tp^.tvrnt, pp);
  1698.                   nfileof:
  1699.                     tp^.tof := xtrenum(tp^.tof, pp);
  1700.  
  1701.                   nptr:
  1702.                     nametype(tp^.tptrid);
  1703.  
  1704.                   nid,
  1705.                   nsubrange,
  1706.                   npredef,
  1707.                   nempty,
  1708.                   nsetof:
  1709.                     (* no op *)
  1710.                 end;(* case *)
  1711.                 tp^.tnext := xtrenum(tp^.tnext, pp)
  1712.                 end;
  1713.             xtrenum := tp
  1714.         end;
  1715.  
  1716.     begin    (* extract *)
  1717.         while tp <> nil do
  1718.             begin
  1719.             (* tp points to a program/procedure/function node *)
  1720.             tp^.tsubtype := xtrenum(tp^.tsubtype, tp);
  1721.             tp^.tsubvar := xtrenum(tp^.tsubvar, tp);
  1722.             vp := tp^.tsubvar;
  1723.             while vp <> nil do
  1724.                 begin
  1725.                 (* variables of structured unnamed types *)
  1726.                 if vp^.tbind^.tt in [nscalar, narray,
  1727.                             nrecord, nfileof] then
  1728.                     vp^.tbind := xtrit(vp^.tbind, tp, true);
  1729.                 vp := vp^.tnext
  1730.                 end;
  1731.             extract(tp^.tsubsub);
  1732.             tp := tp^.tnext
  1733.             end
  1734.     end;    (* extract *)
  1735.  
  1736.     (*    This procedure moves all local constants and types    *)
  1737.     (*    used in nested procedures to the outermost declaration    *)
  1738.     (*    level so that nested procedures may be extracted.    *)
  1739.     procedure global(tp, dp : treeptr; depend : boolean);
  1740.  
  1741.     label    555;
  1742.  
  1743.     var    ip    : treeptr;
  1744.         dep    : boolean;
  1745.  
  1746.         (*    Mark all declared identifiers as unused.    *)
  1747.         procedure markdecl(xp : treeptr);
  1748.  
  1749.         begin
  1750.             while xp <> nil do
  1751.                 begin
  1752.                 case xp^.tt of
  1753.                   nid:
  1754.                     xp^.tsym^.lused := false;
  1755.                   nconst:
  1756.                     markdecl(xp^.tidl);
  1757.                   ntype,
  1758.                   nvar,
  1759.                   nvalpar,
  1760.                   nvarpar,
  1761.                   nfield:
  1762.                     begin
  1763.                     markdecl(xp^.tidl);
  1764.                     if xp^.tbind^.tt <> nid then
  1765.                         markdecl(xp^.tbind)
  1766.                     end;
  1767.                   nscalar:
  1768.                     markdecl(xp^.tscalid);
  1769.                   nrecord:
  1770.                     begin
  1771.                     markdecl(xp^.tflist);
  1772.                     markdecl(xp^.tvlist)
  1773.                     end;
  1774.                   nvariant:
  1775.                     markdecl(xp^.tvrnt);
  1776.                   nconfarr:
  1777.                     if xp^.tcelem^.tt <> nid then
  1778.                         markdecl(xp^.tcelem);
  1779.                   narray:
  1780.                     if xp^.taelem^.tt <> nid then
  1781.                         markdecl(xp^.taelem);
  1782.                   nsetof,
  1783.                   nfileof:
  1784.                     if xp^.tof^.tt <> nid then
  1785.                         markdecl(xp^.tof);
  1786.                   nparproc,
  1787.                   nparfunc:
  1788.                     markdecl(xp^.tparid);
  1789.                   nptr,
  1790.                   nsubrange:
  1791.                     (* no op *)
  1792.                 end;(* case *)
  1793.                 xp := xp^.tnext
  1794.                 end
  1795.         end;    (* markdecl *)
  1796.  
  1797.         (*    Move all marked declarations to global scope.    *)
  1798.         function movedecl(tp : treeptr) : treeptr;
  1799.  
  1800.         var    ip, np    : treeptr;
  1801.             sp    : symptr;
  1802.             move    : boolean;
  1803.  
  1804.         begin
  1805.             if tp <> nil then
  1806.                 begin
  1807.                 move := false;
  1808.                 case tp^.tt of
  1809.                   nconst,
  1810.                   ntype:
  1811.                     ip := tp^.tidl
  1812.                 end;(* case *)
  1813.                 while ip <> nil do
  1814.                     begin
  1815.                     if ip^.tsym^.lused then
  1816.                         begin
  1817.                         move := true;
  1818.                         sp := ip^.tsym;
  1819.                         if sp^.lid^.inref > 1 then
  1820.                           begin
  1821.                             sp^.lid :=
  1822.                             mkrename( 'M', sp^.lid);
  1823.                             sp^.lid^.inref :=
  1824.                                 sp^.lid^.inref - 1
  1825.                           end;
  1826.                         ip := nil
  1827.                         end
  1828.                     else
  1829.                         ip := ip^.tnext
  1830.                     end;
  1831.                 if move then
  1832.                     begin
  1833.                     np := tp^.tnext;
  1834.                     tp^.tnext := nil;
  1835.                     ip := tp;
  1836.                     while ip^.tt <> npgm do
  1837.                         ip := ip^.tup;
  1838.                     tp^.tup := ip;
  1839.                     case tp^.tt of
  1840.                       nconst:
  1841.                         begin
  1842.                         if ip^.tsubconst = nil then
  1843.                             ip^.tsubconst := tp
  1844.                         else begin
  1845.                             ip := ip^.tsubconst;
  1846.                             while ip^.tnext <> nil
  1847.                                 do ip := ip^.tnext;
  1848.                             ip^.tnext := tp
  1849.                              end
  1850.                         end;
  1851.                       ntype:
  1852.                         begin
  1853.                         if ip^.tsubtype = nil then
  1854.                             ip^.tsubtype := tp
  1855.                         else begin
  1856.                             ip := ip^.tsubtype;
  1857.                             while ip^.tnext <> nil
  1858.                                 do ip := ip^.tnext;
  1859.                             ip^.tnext := tp
  1860.                              end
  1861.                         end
  1862.                     end;(* case *)
  1863.                     (* tp is moved, drop it and process
  1864.                        remainder of declarationlist *)
  1865.                     tp := movedecl(np)
  1866.                     end
  1867.                 else
  1868.                     tp^.tnext := movedecl(tp^.tnext)
  1869.                 end;
  1870.             movedecl := tp
  1871.         end;    (* movedecl *)
  1872.  
  1873.         (*    This procedure lifts out variables/parameters    *)
  1874.         (*    used in nested procedures/functions.        *)
  1875.         procedure movevars(tp, vp : treeptr);
  1876.  
  1877.         label    555;
  1878.  
  1879.         var    ep, dp, np    : treeptr;
  1880.             ip        : idptr;
  1881.             sp        : symptr;
  1882.  
  1883.             (*    Move a variable    declaration to global    *)
  1884.             (*    var declaration lists.            *)
  1885.             procedure moveglob(tp, dp : treeptr);
  1886.  
  1887.             begin
  1888.                 while tp^.tt <> npgm do
  1889.                     tp := tp^.tup;
  1890.                 dp^.tup := tp;
  1891.                 dp^.tnext := tp^.tsubvar;
  1892.                 tp^.tsubvar := dp
  1893.             end;
  1894.  
  1895.             (*    Create nodes for saving a global    *)
  1896.             (*    pointer variable.            *)
  1897.             function stackop(decl, glob, loc : treeptr) : treeptr;
  1898.  
  1899.             var    op, ip, dp, tp    : treeptr;
  1900.  
  1901.             begin
  1902.                 (* create a new variable to hold old value
  1903.                    of the global variable during a call *)
  1904.                 ip := newid(mkvariable('F'));
  1905.                 case vp^.tt of
  1906.                   nvarpar,
  1907.                   nvalpar,
  1908.                   nvar:
  1909.                     begin
  1910.                     dp := mknode(nvarpar);
  1911.                     dp^.tattr := areference;
  1912.                     dp^.tidl := ip;
  1913.                     (* use same type as the global var *)
  1914.                     dp^.tbind := decl^.tbind
  1915.                     end;
  1916.                   nparproc,
  1917.                   nparfunc:
  1918.                     begin
  1919.                     dp := mknode(vp^.tt);
  1920.                     dp^.tparid := ip;
  1921.                     dp^.tparparm := nil;
  1922.                     dp^.tpartyp := vp^.tpartyp
  1923.                     end
  1924.                 end;(* case *)
  1925.                 ip^.tup := dp;
  1926.  
  1927.                 (* add variable to declarationlists *)
  1928.                 tp := decl;
  1929.                 while not (tp^.tt in [nproc, nfunc, npgm]) do
  1930.                     tp := tp^.tup;
  1931.                 dp^.tup := tp;
  1932.                 if tp^.tsubvar = nil then
  1933.                     tp^.tsubvar := dp
  1934.                 else begin
  1935.                     tp := tp^.tsubvar;
  1936.                     while tp^.tnext <> nil do
  1937.                         tp := tp^.tnext;
  1938.                     tp^.tnext := dp
  1939.                      end;
  1940.                 dp^.tnext := nil;
  1941.  
  1942.                 (* create an assignment saving value *)
  1943.                 op := mknode(npush);
  1944.                 op^.tglob := glob;
  1945.                 op^.tloc := loc;
  1946.                 op^.ttmp := ip;
  1947.                 stackop := op
  1948.             end;
  1949.  
  1950.             (*    Take a "push" node, create "pop" node    *)
  1951.             (*    and add both to tree.            *)
  1952.             procedure addcode(tp, push : treeptr);
  1953.  
  1954.             var    pop    : treeptr;
  1955.  
  1956.             begin
  1957.                 pop := mknode(npop);
  1958.                 (* share variables with "push"-node *)
  1959.                 pop^.tglob := push^.tglob;
  1960.                 pop^.ttmp := push^.ttmp;
  1961.                 pop^.tloc := nil;
  1962.  
  1963.                 (* add npush to head of statement list *)
  1964.                 push^.tnext := tp^.tsubstmt;
  1965.                 tp^.tsubstmt := push;
  1966.                 push^.tup := tp;
  1967.  
  1968.                 (* add npop to end of statement list *)
  1969.                 while push^.tnext <> nil do
  1970.                     push := push^.tnext;
  1971.                 push^.tnext := pop;
  1972.                 pop^.tup := tp
  1973.             end;
  1974.  
  1975.         begin    (* movevars *)
  1976.             while vp <> nil do
  1977.                 begin
  1978.                 case vp^.tt of
  1979.                   nvar,
  1980.                   nvalpar,
  1981.                   nvarpar:
  1982.                     dp := vp^.tidl;
  1983.                   nparproc,
  1984.                   nparfunc:
  1985.                     begin
  1986.                     dp := vp^.tparid;
  1987.                     if dp^.tsym^.lused then
  1988.                         begin
  1989.                         (* create a var declaration *)
  1990.                         ep := mknode(vp^.tt);
  1991.                         ep^.tparparm := nil;
  1992.                         ep^.tpartyp := vp^.tpartyp;
  1993.                         np := newid(mkrename('G',
  1994.                                 dp^.tsym^.lid));
  1995.                         ep^.tparid := np;
  1996.                         np^.tup := ep;
  1997.                         (* swap id's and symbols *)
  1998.                         sp := np^.tsym;
  1999.                         ip := sp^.lid;
  2000.                         np^.tsym^.lid := dp^.tsym^.lid;
  2001.                         dp^.tsym^.lid := ip;
  2002.                         np^.tsym := dp^.tsym;
  2003.                         dp^.tsym := sp;
  2004.                         np^.tsym^.lsymdecl := np;
  2005.                         dp^.tsym^.lsymdecl := dp;
  2006.                         (* make declaration global *)
  2007.                         moveglob(tp, ep);
  2008.                         (* add save/restore-code *)
  2009.                         addcode(tp, stackop(vp, np, dp))
  2010.                         end;
  2011.                     goto 555
  2012.                     end
  2013.                 end;(* case *)
  2014.                 while dp <> nil do
  2015.                     begin
  2016.                     if dp^.tsym^.lused then
  2017.                         begin
  2018.                         (* create a varpar declaration,
  2019.                            (nvarpar will cause emit to
  2020.                            treat the new identifier
  2021.                            as a pointer) *)
  2022.                         ep := mknode(nvarpar);
  2023.                         ep^.tattr := areference;
  2024.                         np := newid(mkrename('G',
  2025.                                 dp^.tsym^.lid));
  2026.                         ep^.tidl := np;
  2027.                         np^.tup := ep;
  2028.                         ep^.tbind := vp^.tbind;
  2029.                         if ep^.tbind^.tt = nid then
  2030.                             ep^.tbind^.tsym^.lused
  2031.                                 := true;
  2032.                         (* swap id's and symbols *)
  2033.                         sp := np^.tsym;
  2034.                         ip := sp^.lid;
  2035.                         np^.tsym^.lid := dp^.tsym^.lid;
  2036.                         dp^.tsym^.lid := ip;
  2037.                         np^.tsym := dp^.tsym;
  2038.                         dp^.tsym := sp;
  2039.                         np^.tsym^.lsymdecl := np;
  2040.                         dp^.tsym^.lsymdecl := dp;
  2041.                         (* note that dp is referenced *)
  2042.                         dp^.tup^.tattr := aextern;
  2043.                         (* make declaration global *)
  2044.                         moveglob(tp, ep);
  2045.                         (* add save/restore-code *)
  2046.                         addcode(tp, stackop(vp, np, dp))
  2047.                         end;
  2048.                     dp := dp^.tnext
  2049.                     end;
  2050.             555:
  2051.                 vp := vp^.tnext
  2052.                 end
  2053.         end;    (* movevars *)
  2054.  
  2055.         (*    Break out a local variable and set the register    *)
  2056.         (*    attribute.                    *)
  2057.         procedure registervar(tp : treeptr);
  2058.  
  2059.         var    vp, xp    : treeptr;
  2060.  
  2061.         begin
  2062.             vp := idup(tp);
  2063.             tp := tp^.tsym^.lsymdecl;
  2064.             (* vp points to nvar node *)
  2065.             if (vp^.tidl <> tp) or (tp^.tnext <> nil) then
  2066.                 begin
  2067.                 (* tp is not alone in list of identifiers,
  2068.                    create a new nvar-node and hook up tp *)
  2069.                 xp := mknode(nvar);
  2070.                 xp^.tattr := anone;
  2071.                 xp^.tidl := tp;
  2072.                 tp^.tup := xp;
  2073.                 (* enter new nvar node among declarations *)
  2074.                 xp^.tup := vp^.tup;
  2075.                 xp^.tbind := vp^.tbind; (* borrow type *)
  2076.                 xp^.tnext := vp^.tnext;
  2077.                 vp^.tnext := xp;
  2078.                 (* break tp out of list of identifiers *)
  2079.                 if vp^.tidl = tp then
  2080.                     vp^.tidl := tp^.tnext
  2081.                 else begin
  2082.                     vp := vp^.tidl;
  2083.                     while vp^.tnext <> tp do
  2084.                         vp := vp^.tnext;
  2085.                     vp^.tnext := tp^.tnext
  2086.                      end;
  2087.                 tp^.tnext := nil
  2088.                 end;
  2089.             (* tp is alone in this declaration, set attribute *)
  2090.             if tp^.tup^.tattr = anone then
  2091.                 tp^.tup^.tattr := aregister
  2092.         end;    (* registervar *)
  2093.  
  2094.         (*    Check static declarationlevel for a label    *)
  2095.         (*    used in a non-local goto.            *)
  2096.         procedure cklevel(tp : treeptr);
  2097.  
  2098.         begin
  2099.             tp := tp^.tsym^.lsymdecl;
  2100.             while not(tp^.tt in [npgm, nproc, nfunc]) do
  2101.                 tp := tp^.tup;
  2102.             if tp^.tstat > maxlevel then
  2103.                 maxlevel := tp^.tstat
  2104.         end;
  2105.  
  2106.     begin    (* global *)
  2107.         while tp <> nil do
  2108.             begin
  2109.             case tp^.tt of
  2110.               nproc,
  2111.               nfunc:
  2112.                 begin
  2113.                 (* procid/parameters/const/type/var not used *)
  2114.                 markdecl(tp^.tsubid);
  2115.                 markdecl(tp^.tsubpar);
  2116.                 markdecl(tp^.tsubconst);
  2117.                 markdecl(tp^.tsubtype);
  2118.                 markdecl(tp^.tsubvar);
  2119.  
  2120.                 (* mark those used in nested subroutines *)
  2121.                 global(tp^.tsubsub, tp, false);
  2122.  
  2123.                 (* move out variables used in inner scope *)
  2124.                 movevars(tp, tp^.tsubpar);
  2125.                 movevars(tp, tp^.tsubvar);
  2126.                 (* move out const/type used in inner scope *)
  2127.                 tp^.tsubtype := movedecl(tp^.tsubtype);
  2128.                 tp^.tsubconst := movedecl(tp^.tsubconst);
  2129.  
  2130.                 (* mark identifiers used in this subroutine *)
  2131.                 global(tp^.tsubstmt, tp, true);
  2132.                 global(tp^.tsubpar, tp, false);
  2133.                 global(tp^.tsubvar, tp, false);
  2134.                 global(tp^.tsubtype, tp, false);
  2135.                 global(tp^.tfuntyp, tp, false);
  2136.                 end;
  2137.  
  2138.               npgm:
  2139.                 begin
  2140.                 markdecl(tp^.tsubconst);
  2141.                 markdecl(tp^.tsubtype);
  2142.                 markdecl(tp^.tsubvar);
  2143.                 global(tp^.tsubsub, tp, false);
  2144.                 global(tp^.tsubstmt, tp, true)
  2145.                 end;
  2146.  
  2147.               nconst,
  2148.               ntype,
  2149.               nvar,
  2150.               nfield,
  2151.               nvalpar,
  2152.               nvarpar:
  2153.                 begin
  2154.                 ip := tp^.tidl;
  2155.                 dep := depend;
  2156.                 while (ip <> nil) and not dep do
  2157.                     begin
  2158.                     (* for all used identifiers, propagate
  2159.                        the use to their bindings *)
  2160.                     if ip^.tsym^.lused then
  2161.                         dep := true;
  2162.                     ip := ip^.tnext
  2163.                     end;
  2164.                 global(tp^.tbind, dp, dep);
  2165.                 end;
  2166.               nparproc,
  2167.               nparfunc:
  2168.                 begin
  2169.                 global(tp^.tparparm, dp, depend);
  2170.                 global(tp^.tpartyp, dp, depend)
  2171.                 end;
  2172.               nsubrange:
  2173.                 begin
  2174.                 global(tp^.tlo, dp, depend);
  2175.                 global(tp^.thi, dp, depend)
  2176.                 end;
  2177.               nvariant:
  2178.                 begin
  2179.                 global(tp^.tselct, dp, depend);
  2180.                 global(tp^.tvrnt, dp, depend)
  2181.                 end;
  2182.               nrecord:
  2183.                 begin
  2184.                 global(tp^.tflist, dp, depend);
  2185.                 global(tp^.tvlist, dp, depend)
  2186.                 end;
  2187.               nconfarr:
  2188.                 begin
  2189.                 global(tp^.tcindx, dp, depend);
  2190.                 global(tp^.tcelem, dp, depend)
  2191.                 end;
  2192.               narray:
  2193.                 begin
  2194.                 global(tp^.taindx, dp, depend);
  2195.                 global(tp^.taelem, dp, depend)
  2196.                 end;
  2197.               nfileof,
  2198.               nsetof:
  2199.                 global(tp^.tof, dp, depend);
  2200.               nptr:
  2201.                 global(tp^.tptrid, dp, depend);
  2202.               nscalar:
  2203.                 global(tp^.tscalid, dp, depend);
  2204.               nbegin:
  2205.                 global(tp^.tbegin, dp, depend);
  2206.               nif:
  2207.                 begin
  2208.                 global(tp^.tifxp, dp, depend);
  2209.                 global(tp^.tthen, dp, depend);
  2210.                 global(tp^.telse, dp, depend)
  2211.                 end;
  2212.               nwhile:
  2213.                 begin
  2214.                 global(tp^.twhixp, dp, depend);
  2215.                 global(tp^.twhistmt, dp, depend)
  2216.                 end;
  2217.               nrepeat:
  2218.                 begin
  2219.                 global(tp^.treptstmt, dp, depend);
  2220.                 global(tp^.treptxp, dp, depend)
  2221.                 end;
  2222.               nfor:
  2223.                 begin
  2224.                 ip := idup(tp^.tforid);
  2225.                 if ip^.tup^.tt in [nproc, nfunc] then
  2226.                     registervar(tp^.tforid);
  2227.                 global(tp^.tforid, dp, depend);
  2228.                 global(tp^.tfrom, dp, depend);
  2229.                 global(tp^.tto, dp, depend);
  2230.                 global(tp^.tforstmt, dp, depend)
  2231.                 end;
  2232.               ncase:
  2233.                 begin
  2234.                 global(tp^.tcasxp, dp, depend);
  2235.                 global(tp^.tcaslst, dp, depend);
  2236.                 global(tp^.tcasother, dp, depend)
  2237.                 end;
  2238.               nchoise:
  2239.                 begin
  2240.                 global(tp^.tchocon, dp, depend);
  2241.                 global(tp^.tchostmt, dp, depend);
  2242.                 end;
  2243.               nwith:
  2244.                 begin
  2245.                 global(tp^.twithvar, dp, depend);
  2246.                 global(tp^.twithstmt, dp, depend)
  2247.                 end;
  2248.               nwithvar:
  2249.                 begin
  2250.                 ip := typeof(tp^.texpw);
  2251.                 if ip^.tuid = nil then
  2252.                     ip^.tuid := mkvariable('S');
  2253.                 global(tp^.texpw, dp, depend);
  2254.                 end;
  2255.               nlabstmt:
  2256.                 global(tp^.tstmt, dp, depend);
  2257.               neq, nne, nlt, nle, ngt, nge:
  2258.                 begin
  2259.                 global(tp^.texpl, dp, depend);
  2260.                 global(tp^.texpr, dp, depend);
  2261.                 ip := typeof(tp^.texpl);
  2262.                 if (ip = typnods[tstring]) or
  2263.                             (ip^.tt = narray) then
  2264.                     usecomp := true;
  2265.                 ip := typeof(tp^.texpr);
  2266.                 if (ip = typnods[tstring]) or
  2267.                             (ip^.tt = narray) then
  2268.                     usecomp := true
  2269.                 end;
  2270.               nin, nor, nplus, nminus,
  2271.               nand, nmul, ndiv, nmod, nquot,
  2272.               nformat, nrange:
  2273.                 begin
  2274.                 global(tp^.texpl, dp, depend);
  2275.                 global(tp^.texpr, dp, depend)
  2276.                 end;
  2277.  
  2278.               nassign:
  2279.                 begin
  2280.                 global(tp^.tlhs, dp, depend);
  2281.                 global(tp^.trhs, dp, depend)
  2282.                 end;
  2283.  
  2284.               nnot,
  2285.               numinus,
  2286.               nuplus,
  2287.               nderef:
  2288.                 global(tp^.texps, dp, depend);
  2289.               nset:
  2290.                 global(tp^.texps, dp, depend);
  2291.               nindex:
  2292.                 begin
  2293.                 global(tp^.tvariable, dp, depend);
  2294.                 global(tp^.toffset, dp, depend)
  2295.                 end;
  2296.               nselect:
  2297.                 global(tp^.trecord, dp, depend);
  2298.               ncall:
  2299.                 begin
  2300.                 global(tp^.tcall, dp, depend);
  2301.                 global(tp^.taparm, dp, depend)
  2302.                 end;
  2303.               nid:
  2304.                 begin
  2305.                 (* find declaration point *)
  2306.                 ip := idup(tp);
  2307.                 if ip = nil then
  2308.                     goto 555;
  2309.                 (* ip points to nconst/ntype/nvar/nproc/nfunc/
  2310.                    nvalpar/nvarpar/nparproc or nparfunc node,
  2311.                    move to beginning of enclosing scope *)
  2312.                 repeat
  2313.                     ip := ip^.tup;
  2314.                     if ip = nil then
  2315.                         goto 555
  2316.                     (* stop only for locally declared items,
  2317.                        for global or predefined identifiers
  2318.                        we will have gone to label 555 *)
  2319.                 until    ip^.tt in [npgm, nproc, nfunc];
  2320.                 if dp = ip then
  2321.                     begin
  2322.                     (* identifier used here, mark it used *)
  2323.                     if depend then
  2324.                         tp^.tsym^.lused := true
  2325.                     end
  2326.                 else begin
  2327.                     (* identifier declared in enclosing
  2328.                        scope, mark it used *)
  2329.                     tp^.tsym^.lused := true
  2330.                      end;
  2331.             555:
  2332.                 end;
  2333.               ngoto:
  2334.                 if not islocal(tp^.tlabel) then
  2335.                     begin
  2336.                     tp^.tlabel^.tsym^.lgo := true;
  2337.                     usejmps := true;
  2338.                     cklevel(tp^.tlabel)
  2339.                     end;
  2340.  
  2341.               nbreak,
  2342.               npush,
  2343.               npop,
  2344.               npredef,
  2345.               nempty,
  2346.               nchar,
  2347.               ninteger,
  2348.               nreal,
  2349.               nstring,
  2350.               nnil:
  2351.             end;(* case *)
  2352.             tp := tp^.tnext
  2353.             end
  2354.     end;    (* global *)
  2355.  
  2356.     (*    Rename identifiers identical to C keywords.        *)
  2357.     procedure renamc;
  2358.  
  2359.     var    ip    : idptr;
  2360.         cn    : cnames;
  2361.  
  2362.     begin
  2363.         (* rename identifiers that mustn't be redefined
  2364.            if C and Pascal semantix are to be preserved *)
  2365.         for cn := cabort to cwrite do
  2366.             begin
  2367.             ip := mkrename('C', ctable[cn]);
  2368.             ctable[cn]^.istr := ip^.istr
  2369.             end
  2370.     end;
  2371.  
  2372.     (*    Rename subroutines declared in other subroutines such    *)
  2373.     (*    that they can be moved to a global scope without name-    *)
  2374.     (*    clashes.                        *)
  2375.     procedure renamp(tp : treeptr; on : boolean);
  2376.  
  2377.     var    sp    : symptr;
  2378.  
  2379.     begin
  2380.         (* tp points to subroutine-list *)
  2381.         while tp <> nil do
  2382.             begin
  2383.             renamp(tp^.tsubsub, true);
  2384.             if on and (tp^.tsubstmt <> nil) then
  2385.                 begin
  2386.                 (* change name of subroutine by prefixing
  2387.                    a unique name *)
  2388.                 sp := tp^.tsubid^.tsym;
  2389.                 if sp^.lid^.inref > 1 then
  2390.                     begin
  2391.                     sp^.lid := mkrename('P', sp^.lid);
  2392.                     sp^.lid^.inref := sp^.lid^.inref - 1
  2393.                     end
  2394.                 end;
  2395.             tp := tp^.tnext
  2396.             end
  2397.     end;
  2398.  
  2399.     (*    Add initialization-code for file-variables.        *)
  2400.     procedure initcode(tp : treeptr);
  2401.  
  2402.     var    ti, tq, tu, tv    : treeptr;
  2403.  
  2404.         (*    Determine if a type contains a file.        *)
  2405.         function filevar(tp : treeptr) : boolean;
  2406.  
  2407.         var    fv    : boolean;
  2408.             tq    : treeptr;
  2409.  
  2410.         begin
  2411.             case tp^.tt of
  2412.               npredef:
  2413.                 fv := tp = typnods[ttext];
  2414.               nfileof:
  2415.                 fv := true;
  2416.               nconfarr:
  2417.                 fv := filevar(typeof(tp^.tcelem));
  2418.               narray:
  2419.                 fv := filevar(typeof(tp^.taelem));
  2420.               nrecord:
  2421.                 begin
  2422.                 fv := false;
  2423.                 tq := tp^.tvlist;
  2424.                 while tq <> nil do
  2425.                     begin
  2426.                     if filevar(tq^.tvrnt) then
  2427.                         error(evrntfile);
  2428.                     tq := tq^.tnext
  2429.                     end;
  2430.                 tq := tp^.tflist;
  2431.                 while tq <> nil do
  2432.                     begin
  2433.                     if filevar(typeof(tq^.tbind)) then
  2434.                         begin
  2435.                         fv := true;
  2436.                         tq := nil
  2437.                         end
  2438.                     else
  2439.                         tq := tq^.tnext
  2440.                     end
  2441.                 end;
  2442.               nptr:
  2443.                 begin
  2444.                 fv := false;
  2445.                 if not tp^.tptrflag then
  2446.                     begin
  2447.                     tp^.tptrflag := true;
  2448.                     if filevar(typeof(tp^.tptrid)) then
  2449.                         error(evarfile);
  2450.                     tp^.tptrflag := false
  2451.                     end
  2452.                 end;
  2453.               nsubrange,
  2454.               nscalar,
  2455.               nsetof:
  2456.                 fv := false
  2457.             end;
  2458.             filevar := fv
  2459.         end;
  2460.  
  2461.         (*    Create code for initialization of files.    *)
  2462.         function fileinit(ti, tq : treeptr; opn : boolean) : treeptr;
  2463.  
  2464.         var    tx, ty, tz    : treeptr;
  2465.  
  2466.         begin
  2467.             (* create 1 statement initializing "ti" *)
  2468.             case tq^.tt of
  2469.               narray:
  2470.                 begin
  2471.                 (* create declaration for a loopvariable *)
  2472.                 tz := newid(mkvariable('I'));
  2473.                 ty := mknode(nvar);
  2474.                 ty^.tattr := aregister;
  2475.                 ty^.tidl := tz;
  2476.                 ty^.tbind := typeof(tq^.taindx);
  2477.                 tz := tq;
  2478.                 while not(tz^.tt in [nproc, nfunc, npgm]) do
  2479.                     tz := tz^.tup;
  2480.                 linkup(tz, ty);
  2481.                 if tz^.tsubvar = nil then
  2482.                     tz^.tsubvar := ty
  2483.                 else begin
  2484.                     tz := tz^.tsubvar;
  2485.                     while tz^.tnext <> nil do
  2486.                         tz := tz^.tnext;
  2487.                     tz^.tnext := ty
  2488.                      end;
  2489.                 ty := ty^.tidl;
  2490.                 (* create a loop initializing tq *)
  2491.                 tz := mknode(nindex);
  2492.                 tz^.tvariable := ti;
  2493.                 tz^.toffset := ty;
  2494.                 tz := fileinit(tz, tq^.taelem, opn);
  2495.                 tx := mknode(nfor);
  2496.                 tx^.tforid := ty;
  2497.                 ty := typeof(tq^.taindx);
  2498.                 if ty^.tt = nsubrange then
  2499.                     begin
  2500.                     tx^.tfrom := ty^.tlo;
  2501.  
  2502.